﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IronPhpConsole {
    using System.Diagnostics;
    using System.IO;
    using System.Reflection;
    using System.Threading; 

    public class PhpTestHarness {
        public PhpTestHarness(string phpExecutablePath, string testPath) {
            var phpExecutable = File.Exists(phpExecutablePath) ? Path.GetFileName(phpExecutablePath) : null;
            if (phpExecutable != null && phpExecutable.ToLower().CompareTo("php.exe") != 0) {
                Console.WriteLine("PHP Executable path is not correct.");
                return;
            }

            var ironPhpExecutablePath = Assembly.GetExecutingAssembly().Location;
            var currentDirectory = new DirectoryInfo(Environment.CurrentDirectory);
            if (testPath != null) {
                currentDirectory = new DirectoryInfo(testPath);
            }

            var files = currentDirectory.GetFiles("*.php", SearchOption.AllDirectories);
            foreach (var file in files) {
                var path = file.FullName.Replace(currentDirectory.FullName, string.Empty).Replace("\\", " -> ");
                Console.WriteLine("Running test: {0}", path);
                Console.Write("PHP\t\t");
                var phpOutput = this.ExecutePhp(phpExecutablePath, file.FullName);
                Console.WriteLine("Time:\t{0}", phpOutput.Time);
                Console.Write("IronPHP\t\t");
                var ironPhpOutput = this.ExecuteIronPhp(ironPhpExecutablePath, file.FullName);
                Console.WriteLine("Time:\t{0}", ironPhpOutput.Time);
                phpOutput.ReportComparison(ironPhpOutput);
                Console.WriteLine();
            }
        }

        public TestResponse ExecutePhp(string phpExecutable, string phpFile) {
            string parms = string.Format("-f \"{0}\"", phpFile);
            string output;
            string error;
            var psi = new ProcessStartInfo(phpExecutable, parms);
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardError = true;
            psi.WindowStyle = ProcessWindowStyle.Normal;
            psi.UseShellExecute = false;
            DateTime start = DateTime.Now;
            Process php = Process.Start(psi);
            using (StreamReader myOutput = php.StandardOutput) {
                output = myOutput.ReadToEnd();
            }
            using (StreamReader myError = php.StandardError) {
                error = myError.ReadToEnd();
            }
            DateTime end = DateTime.Now;
            var success = string.IsNullOrEmpty(error.Trim());
            var returnValue = new TestResponse
            { Name = "PHP", Success = success, Output = success ? output : error, Time = end - start };
            return returnValue;
        }

        public TestResponse ExecuteIronPhp(string ironPhpExecutable, string phpFile) {
            string parms = string.Format("\"{0}\"", phpFile);
            string output;
            string error;
            var psi = new ProcessStartInfo(ironPhpExecutable, parms);
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardError = true;
            psi.WindowStyle = ProcessWindowStyle.Normal;
            psi.UseShellExecute = false;
            DateTime start = DateTime.Now;
            Process php = Process.Start(psi);
            using (StreamReader myOutput = php.StandardOutput) {
                output = myOutput.ReadToEnd();
            }
            using (StreamReader myError = php.StandardError) {
                error = myError.ReadToEnd();
            }
            DateTime end = DateTime.Now;
            var success = string.IsNullOrEmpty(error.Trim());
            var returnValue = new TestResponse { Name = "IronPHP", Success = success, Output = success ? output : error, Time = end - start };
            return returnValue;
        }
    }
}
